package com.health.personal.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.health.common.core.exception.CaptchaException;
import com.health.common.core.utils.bean.BeanUtils;
import com.health.personal.domain.dto.TDoctorDto;
import com.health.personal.domain.po.TDoctorPo;
import com.health.personal.domain.vo.TDoctorVo;
import com.health.personal.mapper.TDoctorMapper;
import com.health.personal.service.ITDoctorService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.health.common.security.utils.SecurityUtils.encryptPassword;

/**
 * <p>
 * 医生表 服务实现类
 * </p>
 *
 * @author zzs
 * @since 2024-12-12
 */
@Service
@Slf4j
public class TDoctorServiceImpl extends ServiceImpl<TDoctorMapper, TDoctorPo> implements ITDoctorService {

    @Autowired
    private TDoctorMapper mapper;
    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 登录
     * @param email
     * @return
     */
    @Override
    public TDoctorPo login(String  email) {
        // 查询数据库中的医生信息
        LambdaQueryWrapper<TDoctorPo> tDoctorPoLambdaQueryWrapper = Wrappers.lambdaQuery();

        TDoctorPo doctorPo = mapper.selectOne(tDoctorPoLambdaQueryWrapper.eq(TDoctorPo::getEmail, email));

        if (doctorPo == null) {
            throw new RuntimeException("邮箱不存在");
        }
        return doctorPo;
    }

    /**
     * 发送验证码
     * @param doctorDto
     */
    @Override
    public void getCode(TDoctorDto doctorDto) {
        String email = doctorDto.getEmail();
        Integer mino = doctorDto.getMino();
       //邮箱格式正则
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        Pattern pattern = Pattern.compile(emailRegex);
        Matcher matcher = pattern.matcher(email);
        if (email == null || email.isEmpty()) {
            throw new CaptchaException("邮箱不能为空!");
        }
        if (!matcher.matches()) {
            throw new CaptchaException("邮箱格式不正确，请输入正确的邮箱地址!");
        }
        if (mino == null || !(mino == 1 || mino == 2)) {
            throw new IllegalArgumentException("无效的验证码类型!");
        }
        // 生成验证码
        String code = generateVerificationCode();
        // 存储验证码到Redis
        String redisKey = "email:verificationCode:" + email;
        redisTemplate.opsForValue().set(redisKey, code, 1, TimeUnit.MINUTES);

        // 准备邮件内容
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            helper.setFrom("1825075677@qq.com");
            helper.setTo(email);

            // 根据mino设置邮件主题和文本
            String subject, text;
            if (mino == 1) {
                subject = "注册账号验证码通知";
                text = "您的注册验证码是: " + code;
            } else {
                subject = "修改密码验证码通知";
                text = "您的修改密码验证码是: " + code;
            }

            helper.setSubject(subject);
            helper.setText(text);

            // 发送邮件
            javaMailSender.send(mimeMessage);

            // 记录日志
            log.info("验证码已发送到邮箱: {}", email);
        } catch (MessagingException e) {
            // 记录异常信息
            log.error("发送验证码失败: {}", e.getMessage());
            throw new CaptchaException("发送验证码失败!");
        }
    }

    /**
     * 注册
     * @param doctorDto
     */
    @Override
    @Transactional
    public void sign(TDoctorDto doctorDto) {
        // 验证验证码
        String code = doctorDto.getCode();
        String email = doctorDto.getEmail();
        // 构造Redis键
        String redisKey = "email:verificationCode:" + email;
        // 从Redis中获取验证码
        String cachedCode = redisTemplate.opsForValue().get(redisKey);
        if (!cachedCode.equals(code)) {
            throw new CaptchaException("验证码错误！");
        }

        // 构建查询条件并查询数据库
        QueryWrapper<TDoctorPo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        TDoctorPo existingDoctor = mapper.selectOne(queryWrapper);
        if (existingDoctor != null) {
            throw new CaptchaException("该邮箱已注册，请使用其他邮箱进行注册！");
        }

        // 创建新用户并复制属性
        TDoctorPo newDoctor = new TDoctorPo();
        BeanUtils.copyProperties(doctorDto, newDoctor);

        // 添加到数据库
        mapper.insert(newDoctor);
        //删除Redis中的验证码
        redisTemplate.delete(redisKey);
        log.info("用户注册成功，邮箱：{}", email);
    }

    /**
     * 修改密码
     * @param doctorDto
     */
    @Override
    public void changePwd(TDoctorDto doctorDto) throws CaptchaException {
        // 获取验证码和邮箱
        String code = doctorDto.getCode();
        String email = doctorDto.getEmail();

        // 构造Redis键并获取验证码
        String redisKey = "email:verificationCode:" + email;
        String cachedCode = redisTemplate.opsForValue().get(redisKey);

        // 检查验证码是否正确
        if (cachedCode == null || !cachedCode.equals(code)) {
            throw new CaptchaException("验证码错误或已过期！");
        }

        // 对新密码进行加密处理
        String encryptedPassword = encryptPassword(doctorDto.getPassword());

        // 更新密码
        UpdateWrapper<TDoctorPo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("email", email).set("password", encryptedPassword);
        int affectedRows = mapper.update(updateWrapper);

        // 检查更新是否成功
        if (affectedRows <= 0) {
            // 可以根据需要抛出异常或进行其他处理
            throw new RuntimeException("密码更新失败，请稍后再试！");
        }
        //删除Redis中的验证码
        redisTemplate.delete(redisKey);
    }

    /**
     * 医生个人信息
     * @param id
     * @return
     */
    @Override
    public TDoctorVo selByid(Long id) {
            TDoctorVo tDoctorVo = mapper.selByid(id);
        return tDoctorVo;
    }

    /**
     * 生成验证码
     * @return
     */
    public static String generateVerificationCode() {
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            int digit = ThreadLocalRandom.current().nextInt(10);
            code.append(digit);
        }
        return code.toString();
    }

}
